/*
*  Validation Component Js Library V2
*
*/
//["N","Hi","MessageLabel1","false","Please enter your name","3","5","the lenght of name is invalid","^\\w{3,5}$","Please enter a valid name"]

var CW = function() {
    //Initial Validation Componment
    return {
        Version: "2.0",

        ConfigLength: 12,
        /*
        * const value
        */
        Empty_Int: 0,

        MandatoryColor: "#FFC030",

        FailureColor: "#C03000",

        MandatoryMessage: "",

        /* customize validation */

        CustomizeValidations: [],

        _ErrorList: [],

        _Mandatory_Error_Message: "_Mandatory_Error_Message_9527",

        /*
        *  add a event handler to object
        */
        addEvent: function(obj, eventName, handler) {
            if (typeof (obj) != "undifined") {
                if (obj.attachEvent) obj.attachEvent("on" + eventName, handler);
                else if (obj.addEventListener) obj.addEventListener(eventName, handler, false);
            }
        },

        removeEvent: function(obj, eventName, handler) {
            if (typeof (obj) != "undifined") {
                if (obj.detachEvent) obj.detachEvent("on" + eventName, handler);
                else if (obj.removeEventListener) obj.removeEventListener(eventName, handler, false);
            }
        },

        /*
        * Initial Validation Config
        */
        Add: function(buffer) {
            if (buffer.length != CW.ConfigLength) {
                throw "Validation config error.";
            } else {
                var config = new CW.Config();
                var index = CW._convertToInt(buffer[0]);
                if (index == CW.Empty_Int) config.Index = (CW.Validation.Data.length + 1);
                else config.Index = index;
                config.GroupName = buffer[1];
                config.DisplayModel = buffer[2];
                config.ControlID = buffer[3];
                //Test(Dynamic create a message container)
                if (buffer[4].length == "") {
                    var ul = document.createElement("ul");
                    ul.id = config.ControlID + "_Message_Container";
                    //get Next Node
                    var obj = document.getElementById(config.ControlID);
                    var _childs = obj.childNodes;
                    var _nextNode = null;
                    for (var i = 0; i < _childs.length; i++) {
                        if (_childs[i].id == config.ControlID) {
                            if (i < (_childs.length - 1)) // not last one
                                _nextNode = _childs[i + 1];
                            break;
                        }
                    }
                    if (_nextNode != null)
                        obj.parentNode.insertBefore(ul, _nextNode);
                    else
                        obj.parentNode.appendChild(ul);
                    buffer[4] = ul.id;
                    //Add error List
                    ND.AddErrorList({ ID: buffer[4], Title: "", TC: "", MC: "dynamicerror", M: false });
                }
                config.MessageID = buffer[4];
                config.Mandatory = buffer[5]; //CW._convertToBoolean(buffer[5]); -- for test
                config.MMessage = buffer[6];
                config.MinLength = CW._convertToInt(buffer[7]);
                config.MaxLength = CW._convertToInt(buffer[8]);
                config.LMessage = buffer[9];
                config.Regex = buffer[10];
                config.RMessage = buffer[11];
                config.IsEmpty = false;
                CW.Validation.Data.push(config);
            }
        },

        /*
        *  Validate
        */
        Validate: function(groupName) {
            //check mandatory
            var allempty = true;
            if (this.MandatoryMessage.length > 0) {
                for (var i = 0; i < CW.Validation.Data.length; i++) {
                    if (groupName == "" || typeof (groupName) == "undefined" || CW.Validation.Data[i].GroupName == groupName) {
                        var obj = document.getElementById(CW.Validation.Data[i].ControlID);
                        if (obj != null) {
                            var config = CW.Get(CW.Validation.Data[i].ControlID);
                            if (config.Mandatory && obj.value != "") {
                                allempty = false;
                                break;
                            }
                        }
                    }
                }
                if (allempty) {
                    //Customize Validation
                    for (var i = 0; i < CW.CustomizeValidations.length; i++) {
                        if (groupName == "" || typeof (groupName) == "undefined" || CW.CustomizeValidations[i].GroupName == groupName) {
                            var r = CW.CustomizeValidations[i].Validate(result);
                            if (r == true) {
                                allempty = false;
                                break;
                            }
                        }
                    }
                }

                if (allempty) {
                    for (var i = 0; i < this._ErrorList.length; i++) {
                        this._ErrorList[i].Message = []; //clear all message
                        if (this._ErrorList[i].UseForMandatory == true) {
                            CW.AddErrorMessage(this._ErrorList[i].ID, CW._Mandatory_Error_Message, CW.MandatoryMessage);
                        }
                    }
                    CW._display();
                    return false;
                }
            }

            //=========================================================================================================
            var result = true;
            for (var i = 0; i < CW.Validation.Data.length; i++) {
                if (groupName == "" || typeof (groupName) == "undefined" || CW.Validation.Data[i].GroupName == groupName) {
                    var obj = document.getElementById(CW.Validation.Data[i].ControlID);
                    if (obj != null) {
                        var e = Object();
                        e.srcElement = obj;
                        result = (result == 1 ? true : false) & CW.Validation.ControlValidation(e);
                    }
                }
            }
            result = (result == 1 || result ? true : false);
            //Customize Validation
            for (var i = 0; i < CW.CustomizeValidations.length; i++) {
				if (ND.CustomizeValidations[i].GroupName == "" ||
                    ND.CustomizeValidations[i].GroupName == groupName) {
	                var r = CW.CustomizeValidations[i].Validate(result);
	                //remove mandaotry message
	                CW.RemoveMessage(CW.CustomizeValidations[i].MessageContainer, CW._Mandatory_Error_Message);

	                if (r == false) {
	                    result = false;
	                    CW.AddErrorMessage(CW.CustomizeValidations[i].MessageContainer, CW.CustomizeValidations[i].UniqueID, CW.CustomizeValidations[i].Message);
	                } else {
	                    CW.RemoveMessage(CW.CustomizeValidations[i].MessageContainer, CW.CustomizeValidations[i].UniqueID);
	                }
				}
            }

            //Show Error Message
            CW._display();
            return (result == 1 || result ? true : false);
        },

        /* 
        * Customize validation
        */
        AddCustomize: function(fun) {
            if (CW.CustomizeValidations == null) CW.CustomizeValidations = [];
            CW.CustomizeValidations.push(fun);
            return fun.UniqueID;
        },

        RemoveCustomize: function(uniqueID) {
            if (CW.CustomizeValidations != null) {
                for (var i = 0; i < CW.CustomizeValidations.length; i++) {
                    if (CW.CustomizeValidations[i].UniqueID == uniqueID) {
                        CW.CustomizeValidations.splice(i, 1);
                        break;
                    }
                }
            }
        },

        /*
        * return validation config for UniqueID
        */
        Get: function(uniqueID) {
            for (var i = 0; i < CW.Validation.Data.length; i++) {
                if (CW.Validation.Data[i].ControlID == uniqueID)
                    return CW.Validation.Data[i];
            }
            return new CW.Config();
        },

        AddErrorList: function(obj) {
            var error = CW.ErrorList();
            error.ID = obj.ID;
            error.Title = obj.Title;
            error.TitleClass = obj.TC;
            error.MessageClass = obj.MC;
            error.UseForMandatory = obj.M;
            this._ErrorList.push(error);
        },

        AddErrorMessage: function(messageID, uniqueID, message) {
            for (var i = 0; i < this._ErrorList.length; i++) {
                if (this._ErrorList[i].ID == messageID) {
                    this._ErrorList[i].AddMessage(uniqueID, message);
                    break;
                }
            }
        },

        RemoveMessage: function(messageID, uniqueID) {
            for (var i = 0; i < this._ErrorList.length; i++) {
                if (this._ErrorList[i].ID == messageID) {
                    this._ErrorList[i].RemoveMessage(uniqueID);
                    break;
                }
            }
        },

        //****************** private method ***********************
        _convertToInt: function(obj) {
            try {
                var r = parseInt(obj);
                return r;
            } catch (e) { return CW.Empty_Int }
        },

        _convertToBoolean: function(obj) {
            try {
                return new Boolean(obj);
            }
            catch (e) { return false; }
        },

        _getEventHandler: function(uniqueID, eventType) {
            var _handlers = [];
            for (var i = 0; i < CW.Handler.Source.length; i++) {
                if (CW.Handler.Source[i].UniqueID == uniqueID && CW.Handler.Source[i].EventType == eventType)
                    _handlers.push(CW.Handler.Source[i]);
            }
            _handlers.sort(function(r1, r2) {
                return r1.Index - r2.Index;
            });
            return _handlers;
        },

        _display: function() {
            //reset ErrorList
            for (var i = 0; i < CW._ErrorList.length; i++) {
                CW._ErrorList[i].Show();
            }
        }
    }
} ();

CW.Config = function() {
    /*
    *  ControlID is a unique ID for the validation config. 
    *  For control validation that is control id, for Customize validation that is a guid id. 
    */
    return {
        Index: 0,
        GroupName: "",
        DisplayModel: "",
        ControlID: "",
        MessageID: "",
        Mandatory: false,
        MMessage: "",
        MinLength: "",
        MaxLength: "",
        LMessage: "",
        Regex: "",
        RMessage: "",
        /*
        * Default value is True
        */
        IsEmpty: true,
        /* Control Background Color */
        _bgColor: null
    }
}

CW.Validation = function() {
    return {
        /*
        * Validation Setting Array 
        */
        Data: [],
        /*
        *  Validation Message Showing Helper 
        */
        MessageShowHelper: [],
        /*
        * Initial auto validation when content change or control lose focus
        */
        Initial: function() {
            if (this.Data.length > 0) {
                for (var i = 0; i < this.Data.length; i++) {
                    var obj = document.getElementById(this.Data[i].ControlID);
                    if (obj.tagName.toUpperCase() == "INPUT" &&
                    ((obj.attributes["type"].value.toUpperCase() == "TEXT" || obj.attributes["type"].value.toUpperCase() == "PASSWORD")) || (obj.tagName.toUpperCase() == "TEXTAREA")) {
                        this.Data[i]._bgColor = obj.style.backgroundColor;
                        CW.addEvent(obj, "blur", this._lostFocusValidate);
                    }
                }
            }
        },

        _lostFocusValidate: function(e) {
            var result = CW.Validation.ControlValidation(e);
            CW._display();
            return result;
        },

        ControlValidation: function(e) {
            var obj = (e.target) ? e.target : e.srcElement;
            var uniqueID = obj.id;
            var value = obj.value;
            var config = CW.Get(uniqueID);
            //var _Message = new CW.MessageShow("Each");
            //CW.ErrorMessage.push(_Message);
            //_Message.MessageContainer = config.MessageID;

            var result = CW.ValidationResult();

            //event Before
            var _beforeHandler = CW._getEventHandler(uniqueID, CW.EventType.Before);
            for (var i = 0; i < _beforeHandler.length; i++) {
                var _br;
                if (i == 0)
                    _br = _beforeHandler[i].Handler(value, true);
                else
                    _br = _beforeHandler[i].Handler(value, ((result.Result == 1) ? true : false));

                // if event handler don't have any return value, use defaut value replace
                if (typeof (_br) == "undefined") _br = CW.ValidationResult();

                if (!_br) {
                    result.Result &= _br;
                    result.Message = _beforeHandler[i].Message;
                }

                //8/04/2009(test)
                //Cancel validate, use Event result instead of the validate result
                if (_beforeHandler[i].CancelValidate) {
                    CW.AddErrorMessage(config.MessageID, uniqueID, _beforeHandler[i].Message);
                    return _br;
                }

                if (!_beforeHandler[i].Bubble)
                    break;
            }

            //if event return false, cancel others validate.
            if (result.Result == 0 || !result.Result) {
                CW.AddErrorMessage(config.MessageID, uniqueID, result.Message);
                return result.Result;
            }

            var _result = CW.Validation._Validate(obj, value, uniqueID);
            result.Result &= _result.Result;
            result.Message = _result.Message;

            //event After
            var _afterHandler = CW._getEventHandler(uniqueID, CW.EventType.After);
            for (var i = 0; i < _afterHandler.length; i++) {
                var _ar = _afterHandler[i].Handler(value, ((result.Result == 1) ? true : false));
                if (!_ar) {
                    result.Result &= _ar;
                    result.Message = _afterHandler[i].Message;
                }
                if (!_afterHandler[i].Bubble)
                    break;
            }

            //Push error Message
            //_Message.AddMessage(uniqueID, result.Message);
            CW.AddErrorMessage(config.MessageID, uniqueID, result.Message);
            //remove mandatory message
            CW.RemoveMessage(config.MessageID, CW._Mandatory_Error_Message);
            return result.Result;
        },

        /*
        *  Validation Method
        *  
        *  value: the value need validate
        *  uniqueID : validation config id(ControlID or Guid)
        */
        _Validate: function(obj, value, uniqueID) {
            var result = CW.ValidationResult();
            result.UniqueID = uniqueID;
            var config = CW.Get(uniqueID);
            if (!config.IsEmpty) {
                if (value == "" && config.Mandatory == false) {
                    result.Result = true;
                    result.Message = "";
                }
                else {
                    if (value == "" && config.Mandatory == true) {
                        result.Result = false;
                        result.Message = config.MMessage;
                        CW.Validation._changebgColor(obj, CW.MandatoryColor);
                    } else if (value.length < config.MinLength || value.length > config.MaxLength) {
                        result.Result = false;
                        result.Message = config.LMessage;
                        CW.Validation._changebgColor(obj, CW.FailureColor);
                    } else {
                        var _reg = new RegExp(config.Regex);
                        if (!_reg.test(value)) {
                            result.Result = false;
                            result.Message = config.RMessage;
                            CW.Validation._changebgColor(obj, CW.FailureColor);
                        }
                    }
                }
            }
            if (result.Result) {
                CW.Validation._restorebgColor(obj);
            }
            return result;
        },
        //Change Css
        _changebgColor: function(obj, color) {
            obj.style.backgroundColor = color;
        },
        _restorebgColor: function(obj) {
            var uniqueID = obj.id;
            var config = CW.Get(uniqueID);
            obj.style.backgroundColor = config._bgColor;
        },

        restorebgColor: function(obj) {
            CW.Validation._restorebgColor(obj);
        }
    }
} ();

CW.ControlMessage = function(uniqueID, message) {
    return {
        Type: "Message",
        UniqueID: uniqueID,
        Message: message
    }
}

CW.ErrorList = function() {
    return {
        ID: "",
        Title: "",
        TitleClass: "",
        MessageClass: "",
        UseForMandatory: false,
        Message: [],
        AddMessage: function(uniqueID, message) {
            var add = false;
            for (var i = 0; i < this.Message.length; i++) {
                if (this.Message[i].UniqueID == uniqueID) {
                    this.Message[i].Message = message;
                    add = true;
                    break;
                }
            }
            if (!add) {
                var cMessage = CW.ControlMessage(uniqueID, message);
                this.Message.push(cMessage);
            }
        },
        RemoveMessage: function(uniqueID) {
            for (var i = 0; i < this.Message.length; i++) {
                if (this.Message[i].UniqueID == uniqueID) {
                    this.Message.splice(i, 1);
                    break;
                }
            }
        },
        Show: function() {
            this.Clear();

            if (typeof (this.CustomizeShow) == "function") {
                for (var i = 0; i < this.Message.length; i++) {
                    this.CustomizeShow(this.Message[i].Message);
                }
            } else {
                //show title
                if (this.Message.length > 0 && this.Title != "") {
                    var li = document.createElement("li");
                    li.innerHTML = this.Title;
                    li.className = this.TitleClass;
                    document.getElementById(this.ID).appendChild(li);
                }

                for (var i = 0; i < this.Message.length; i++) {
                    if (this.Message[i].Message != "") { //if message is empty, don't display
                        var li = document.createElement("li");
                        li.innerHTML = this.Message[i].Message;
                        li.className = this.MessageClass;
                        document.getElementById(this.ID).appendChild(li);
                    }
                }
            }
        },
        Clear: function() {
            if (typeof (this.CustomizeClear) == "function") {
                this.CustomizeClear();
            } else {
                document.getElementById(this.ID).innerHTML = "";
            }
        },
        CustomizeShow: null,
        CustomizeClear: null
    }
}

CW.ValidationResult = function() {
    return {
        UniqueID: "",
        Result: true,
        Message: ""
    }
}

CW.EventType = function() {
    return {
        Before: "Before",
        After: "After"
    }
} ();

CW.Handler = function() {
    return {
        Source: [],
        Add: function(handler) {
            if (CW._convertToInt(handler.Index) == CW.Empty_Int) {
                handler.Index = CW._getEventHandler(handler.UniqueID, handler.EventType).length + 1;
            }
            this.Source.push(handler);
            return handler.Guid;
        },
        Remove: function(eventhandler_guid) {
            for (var i = 0; i < this.Source.length; i++) {
                if (this.Source[i].Guid == eventhandler_guid) {
                    this.Source.splice(i, 1);
                    break;
                }
            }
        }
    }
} ();


CW.EventHandler = function(uniqueID, eventType) {
    var guid = CW.Handler.Source.length + 1;
    var _index = CW.Empty_Int;
    return {
        //User to sort the event handler 
        Index: _index,
        Guid: "EventHandler_" + guid,
        EventType: eventType,
        UniqueID: uniqueID,
        CancelValidate: false,
        //Validation result message
        Message: "",
        Bubble: true,
        Handler: function(value, result) {
            return true;
        }
    }
}

CW.Customize = function(errorListID) {
    var _uniqueID = "CustomizeValidation_" + (CW.CustomizeValidations.length + 1);
    return {
        UnqiueID: _uniqueID,
        Message: "",
        MessageContainer: errorListID,
        GroupName: "",
        Validate: function(r) {
            this.Message = "";
            return true;
        }
    }
}
